﻿using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using SPContentDatabaseManager.Layouts;
using System;
using System.Collections.Generic;
using System.Web;

namespace SPContentDatabaseManager.Layouts.SPContentDatabaseManager
{
    /* 
    *********************************************************************
    * Copyright 2014, Ryan Dennis
    * ryan@sharepointryan.com
    * www.sharepointryan.com
    * @SharePointRyan on Twitter
    * Ryan works for Blue Chip Consulting Group, www.bluechip-llc.com
    * All code is provided with no warranty or guarantees.
    * Visit the codeplex site: https://spcontentdbmanager.codeplex.com
     * Feel free to modify this code, but please leave this section 
     * in to give the original author credit.
    *********************************************************************
    */
    public partial class MoveSPSite : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //OKbutton.Enabled = false;
        }
        protected void SiteFromQueryString(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                // Set site collection from query string
                String siteGuid = Request.QueryString["SiteId"];
                SelectedSiteCollection.CurrentId = siteGuid;
            }
        }
        protected void SiteCollectionOnLoad(object sender, EventArgs e)
        {
            var spsite = SelectedSiteCollection;
            var dbName = "";
            using (SPSite selectedSite = new SPSite(SelectedSiteCollection.CurrentItem.Url.ToString()))
            {
                dbName = selectedSite.ContentDatabase.Name.ToString();
                if (dbName != null)
                {
                    CurrentDatabase.Text = dbName;
                }
                CurrentSiteUsage.Text = ((selectedSite.Usage.Storage / 1024f) / 1024f).ToString("0.00 MB");
            }
        }
        protected void DatabaseSelector_OnLoad(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                var spsite = SelectedSiteCollection;
                using (SPSite selectedSite = new SPSite(SelectedSiteCollection.CurrentItem.Url.ToString()))
                {
                    Dictionary<string, Guid> dbList = new Dictionary<string, Guid>();
                    for (int i = 0; i < selectedSite.WebApplication.ContentDatabases.Count; i++)
                    {
                        SPContentDatabase currentDb = selectedSite.WebApplication.ContentDatabases[i];
                        // Only add other databases, not the current database
                        if (currentDb.Name != CurrentDatabase.Text.ToString())
                        {
                            dbList.Add(currentDb.Name, currentDb.Id);
                            DatabaseSelector.DataSource = dbList;
                            DatabaseSelector.DataTextField = "Key";
                            DatabaseSelector.DataValueField = "Value";
                            DatabaseSelector.DataBind();
                        }
                    }
                    DatabaseSelector.Items.Insert(0, "Select a database...");
                    selectedSite.Dispose();
                }
            }
        }
        protected void OnDbChange(object sender, EventArgs e)
        {
            //On Dropdown Change
            SPSite siteToMove = new SPSite(SelectedSiteCollection.CurrentItem.Url.ToString());
            String guidStr = DatabaseSelector.SelectedValue;
            Guid dbGuid = new Guid(guidStr);
            SPContentDatabase destinationDatabase = siteToMove.WebApplication.ContentDatabases[dbGuid];
            Int32 maxSites = destinationDatabase.MaximumSiteCount;
            Int32 afterSiteCount = destinationDatabase.Sites.Count + 1;
            String sourceName = CurrentDatabase.ToString();
            String destName = destinationDatabase.Name.ToString();
            // Set database detail table properties
            DestDatabaseSiteCount.Text = destinationDatabase.Sites.Count.ToString();
            DestDatabaseSize.Text = Utilities.FormatBytes(destinationDatabase.DiskSizeRequired);
            DestDatabaseName.Text = destinationDatabase.Name.ToString();
            DestDatabaseMaxSiteCount.Text = destinationDatabase.MaximumSiteCount.ToString();
            DestDatabaseStatus.Text = destinationDatabase.Status.ToString();
            DestDatabaseReadOnly.Text = destinationDatabase.IsReadOnly.ToString();
            if (sourceName.Equals(destName))
            {
                errorNode.Text = "ERROR: The destination content database must be different from the source content database.";
                OKbutton.Enabled = false;
            }
            else
            {
                errorNode.Text = "";
                OKbutton.Enabled = true;
            }
            if (afterSiteCount > maxSites)
            {
                errorNode.Text = "ERROR: The specified content database has a maximum site count of " + maxSites + " , and cannot contain any more sites. Please choose another content database, or create a new content database.";
                OKbutton.Enabled = false;
            }
            else
            {
                errorNode.Text = "";
                OKbutton.Enabled = true;
            }
            siteToMove.Dispose();
        }
        protected void OKbuttonClick(object sender, EventArgs e)
        {
            SPSite siteToMove = new SPSite(SelectedSiteCollection.CurrentItem.Url.ToString());
            if (siteToMove.ContentDatabase != null)
            {
                String guidStr = DatabaseSelector.SelectedValue;
                Guid dbGuid = new Guid(guidStr);
                SPContentDatabase sourceDatabase = siteToMove.ContentDatabase;
                SPContentDatabase destinationDatabase = siteToMove.WebApplication.ContentDatabases[dbGuid];
                List<SPSite> siteList = new List<SPSite>();
                Dictionary<SPSite, String> failedSites = new Dictionary<SPSite, String>();
                siteList.Add(siteToMove);
                MoveSite(sourceDatabase, destinationDatabase, siteList, failedSites);
                siteToMove.Dispose();
            }
        }
        public void MoveSite(SPContentDatabase sourceDatabase, SPContentDatabase destinationDatabase, List<SPSite> siteList, Dictionary<SPSite, String> failedSites)
        {
            using (new SPMonitoredScope("MoveSPSite"))
            {
                foreach (SPSite currSite in siteList)
                {
                    try
                    {
                        SPLongOperation spLongOperation = new SPLongOperation(this);
                        spLongOperation.LeadingHTML = "Moving " + currSite.RootWeb.Title + " site collection to " + destinationDatabase.Name.ToString();
                        spLongOperation.TrailingHTML = "This may take a few minutes...";
                        spLongOperation.Begin();
                        string redirectUrl = "/_admin/SPContentDbMgr/MoveSPSiteComplete.aspx";
                        currSite.ContentDatabase.Move(destinationDatabase, siteList, out failedSites);
                        spLongOperation.End(redirectUrl, SPRedirectFlags.Static, HttpContext.Current, null);
                    }
                    catch (SPException error)
                    {
                        errorNode.Text = error.ToString();
                        string qs = "errorText=" + error.ToString();
                        HttpContext.Current.RewritePath(HttpContext.Current.Request.Path, null, qs);
                    }
                    finally
                    {
                        currSite.Dispose();
                    }
                }
            }
        }
    }
}
